home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / muds / pennmush.000 / pennmush-1.50-p8-linux.tar / pennmush / flags.c < prev    next >
C/C++ Source or Header  |  1993-04-15  |  21KB  |  847 lines

  1. /* flags.c */
  2.  
  3. /* Functions to cope with flags */
  4.  
  5. #include <sys/time.h>
  6.  
  7. #include "db.h"
  8. #include "externs.h"
  9. #include "interface.h"
  10.  
  11. #define FLAG_HASH_SIZE 256
  12. #define FLAG_HASH_MASK 255
  13.  
  14. typedef struct flag_info FLAG;
  15.  
  16. struct flag_info {
  17.   const char *name;
  18.   char letter;
  19.   int type;
  20.   int flag;
  21.   int perms;
  22.   FLAG *next;
  23. };
  24.  
  25. typedef struct flag_entry FLAGENT;
  26.  
  27. struct flag_entry {
  28.   const char *name;
  29.   FLAG *entry;
  30.   FLAGENT *next;
  31. };
  32.  
  33. typedef struct flag_alias FLAG_ALIAS;
  34.  
  35. struct flag_alias {
  36.   const char *alias;
  37.   const char *realname;
  38. };
  39.  
  40. static FLAGENT *flag_hashtab[FLAG_HASH_SIZE];
  41.   
  42. FLAG flag_table[] =
  43. {
  44.  
  45.   { "CHOWN_OK", 'C',    NOTYPE,        CHOWN_OK,    F_ANY },
  46.   { "DARK",     'D',     NOTYPE,     DARK,        F_ANY },
  47.   { "GOING",    'G',    NOTYPE,        GOING,        F_ANY },
  48.   { "HAVEN",     'H',     NOTYPE,     HAVEN,        F_ANY },
  49. #ifdef INHERIT_FLAG
  50.   { "INHERIT",    'I',    NOTYPE,        INHERIT,    F_INHERIT },
  51. #endif
  52.   { "LINK_OK",     'L',     NOTYPE,     LINK_OK,    F_ANY },
  53.   { "OPAQUE",    'O',    NOTYPE,        OPAQUE,        F_ANY },
  54.   { "QUIET",    'Q',    NOTYPE,        QUIET,        F_ANY },
  55.   { "STICKY",    'S',    NOTYPE,        STICKY,        F_ANY },
  56.   { "UNFINDABLE", 'U',    NOTYPE,        UNFIND,        F_ANY },
  57.   { "VISUAL",    'V',    NOTYPE,        VISUAL,        F_ANY },
  58.   { "WIZARD",    'W',     NOTYPE,     WIZARD,        F_INHERIT | F_WIZARD },
  59.   { "SAFE",    'X',    NOTYPE,        SAFE,        F_ANY },
  60.   { "AUDIBLE",  'a',    NOTYPE,        AUDIBLE,    F_ANY },
  61.   { "DEBUG",    'b',    NOTYPE,        DEBUGGING,         F_INHERIT | F_ROYAL },
  62.   { "ENTER_OK", 'e',    NOTYPE,        ENTER_OK,    F_ANY },
  63.   { "HALT",     'h',    NOTYPE,        HALT,        F_ANY },
  64.   { "NO_COMMAND", 'n',    NOTYPE,        NO_COMMAND,    F_ANY },
  65. #ifdef ROYALTY_FLAG
  66.   { "ROYALTY",    'r',    NOTYPE,        ROYALTY,    F_INHERIT | F_ROYAL },
  67. #endif
  68.   { "TRANSPARENT", 't', NOTYPE,        TRANSPARENT,    F_ANY },
  69.   { "VERBOSE",    'v',    NOTYPE,        VERBOSE,    F_ANY },
  70.   { "STARTUP",  'z',    NOTYPE,        STARTUP,    F_INTERNAL },
  71.  
  72.   { "ANSI",    'A',     TYPE_PLAYER,    PLAYER_ANSI,    F_ANY },
  73.   { "MONITOR",    'M',    TYPE_PLAYER,    PLAYER_MONITOR, F_ROYAL },
  74.   { "NOSPOOF",    'N',    TYPE_PLAYER,    PLAYER_NOSPOOF,    F_ANY },
  75.   { "ZONE",     'Z',    TYPE_PLAYER,    PLAYER_ZONE,    F_ANY },
  76.   { "CONNECTED", 'c',    TYPE_PLAYER,    PLAYER_CONNECT,    F_INTERNAL },
  77.   { "GAGGED",    'g',    TYPE_PLAYER,    PLAYER_GAGGED,    F_WIZARD },
  78.   { "MYOPIC",    'm',    TYPE_PLAYER,    PLAYER_MYOPIC,  F_ANY },
  79.   { "TERSE",    'x',    TYPE_PLAYER,    PLAYER_TERSE,    F_ANY },
  80.   { "SUSPECT",    'u',    TYPE_PLAYER,    PLAYER_SUSPECT,    F_WIZARD },
  81.  
  82.   { "DESTROY_OK", 'd',    TYPE_THING,    THING_DEST_OK,    F_ANY },
  83.   { "LISTENER",    'l',    TYPE_THING,    THING_LISTEN,    F_ANY },
  84.   { "PUPPET",    'p',    TYPE_THING,    THING_PUPPET,    F_ANY },
  85.  
  86.   { "ABODE",    'A',    TYPE_ROOM,    ROOM_ABODE,    F_ANY },
  87.   { "FLOATING",    'F',    TYPE_ROOM,    ROOM_FLOATING,    F_ANY },
  88.   { "JUMP_OK",    'J',    TYPE_ROOM,    ROOM_JUMP_OK,    F_ANY },
  89.   { "NO_TEL",    'N',    TYPE_ROOM,    ROOM_NO_TEL,    F_ANY },
  90.   { "TEMPLE",    'T',    TYPE_ROOM,    ROOM_TEMPLE,    F_ANY },
  91.  
  92.   { "ACCESSED", '\0',    NOTYPE,        ACCESSED,    F_INTERNAL },
  93.   { "MARKED",    '\0',    NOTYPE,        MARKED,        F_INTERNAL },
  94.   { NULL,     '\0',     0,        0,        0 }
  95. };
  96.  
  97. FLAG type_table[] =
  98. {
  99.   { "PLAYER",    'P',    TYPE_PLAYER,    TYPE_PLAYER,    F_INTERNAL },
  100.   { "ROOM",    'R',    TYPE_ROOM,    TYPE_ROOM,    F_INTERNAL },
  101.   { "EXIT",    'E',    TYPE_EXIT,    TYPE_EXIT,    F_INTERNAL },
  102.   { "THING",    'T',    TYPE_THING,    TYPE_THING,    F_INTERNAL },
  103.   { NULL,    '\0',    0,        0,        0 }
  104. };
  105.  
  106. static FLAG_ALIAS flag_alias_tab[] =
  107. {
  108.     { "CHOWN_O",         "CHOWN_OK" },
  109.     { "CHOWN_",        "CHOWN_OK" },
  110.      { "CHOWN",         "CHOWN_OK" },
  111.     { "CHOW",        "CHOWN_OK" },
  112.     { "CHO",         "CHOWN_OK" },
  113.     { "CH",             "CHOWN_OK" },
  114.     { "DAR",        "DARK" },
  115.     { "DA",            "DARK" },
  116.     { "GOIN",        "GOING" },
  117.     { "GOI",        "GOING" },
  118.     { "GO",            "GOING" },
  119.     { "HAVE",        "HAVEN" },
  120.     { "HAV",        "HAVEN" },
  121. #ifdef INHERIT_FLAG
  122.     { "INHERI",        "INHERIT" },
  123.     { "INHER",        "INHERIT" },
  124.     { "INHE",        "INHERIT" },
  125.     { "INH",        "INHERIT" },
  126.     { "IN",            "INHERIT" },
  127.     { "I",            "INHERIT" },
  128. #endif    
  129.     { "LINK_O",        "LINK_OK" },
  130.     { "LINK_",        "LINK_OK" },
  131.     { "LINK",        "LINK_OK" },
  132.     { "LIN",        "LINK_OK" },
  133.     { "OPAQU",        "OPAQUE" },
  134.     { "OPAQ",        "OPAQUE" },
  135.     { "OPA",        "OPAQUE" },
  136.     { "OP",            "OPAQUE" },
  137.     { "O",            "OPAQUE" },
  138.     { "QUIE",        "QUIET" },
  139.     { "QUI",        "QUIET" },
  140.     { "QU",            "QUIET" },
  141.     { "Q",            "QUIET" },
  142.     { "STICK",        "STICKY" },
  143.     { "STIC",        "STICKY" },
  144.     { "STI",        "STICKY" },
  145.     { "ST",            "STICKY" },
  146.     { "UNFINDABL",        "UNFINDABLE" },
  147.     { "UNFINDABL",        "UNFINDABLE" },
  148.     { "UNFINDAB",        "UNFINDABLE" },
  149.     { "UNFINDA",        "UNFINDABLE" },
  150.     { "UNFIND",        "UNFINDABLE" },
  151.     { "UNFIN",        "UNFINDABLE" },
  152.     { "UNFI",        "UNFINDABLE" },
  153.     { "UNF",        "UNFINDABLE" },
  154.     { "UN",            "UNFINDABLE" },
  155.     { "U",            "UNFINDABLE" },
  156.     { "VISUA",        "VISUAL" },
  157.     { "VISU",        "VISUAL" },
  158.     { "VIS",        "VISUAL" },
  159.     { "VI",            "VISUAL" },
  160.     { "WIZAR",        "WIZARD" },
  161.     { "WIZA",        "WIZARD" },
  162.     { "WIZ",        "WIZARD" },
  163.     { "WI",            "WIZARD" },
  164.     { "W",            "WIZARD" },
  165.     { "SAF",        "SAFE" },
  166.     { "SA",            "SAFE" },
  167.     { "AUDIBL",        "AUDIBLE" },
  168.     { "AUDIB",        "AUDIBLE" },
  169.     { "AUDI",        "AUDIBLE" },
  170.     { "AUD",        "AUDIBLE" },
  171.     { "AU",            "AUDIBLE" },
  172.     { "DEBU",        "DEBUG" },
  173.     { "DEB",        "DEBUG" },
  174.     { "ENTER_O",        "ENTER_OK" },
  175.     { "ENTER_",        "ENTER_OK" },
  176.     { "ENTER",        "ENTER_OK" },
  177.     { "ENTE",        "ENTER_OK" },
  178.     { "ENT",        "ENTER_OK" },
  179.     { "EN",            "ENTER_OK" },
  180.     { "HAL",        "HALT" },
  181.     { "NO_COMMAN",        "NO_COMMAND" },
  182.     { "NO_COMMA",        "NO_COMMAND" },
  183.     { "NO_COMM",        "NO_COMMAND" },
  184.     { "NO_COM",        "NO_COMMAND" },
  185.     { "NO_CO",        "NO_COMMAND" },
  186.     { "NO_C",        "NO_COMMAND" },
  187. #ifdef ROYALTY_FLAG
  188.     { "ROYALT",        "ROYALTY" },
  189.     { "ROYAL",        "ROYALTY" },
  190.     { "ROYA",        "ROYALTY" },
  191.     { "ROY",        "ROYALTY" },
  192. #endif
  193.     { "TRANSPAREN",        "TRANSPARENT" },
  194.     { "TRANSPARE",        "TRANSPARENT" },
  195.     { "TRANSPAR",        "TRANSPARENT" },
  196.     { "TRANSPA",        "TRANSPARENT" },
  197.     { "TRANSP",        "TRANSPARENT" },
  198.     { "TRANS",        "TRANSPARENT" },
  199.     { "TRAN",        "TRANSPARENT" },
  200.     { "TRA",        "TRANSPARENT" },
  201.     { "TR",            "TRANSPARENT" },
  202.     { "VERBOS",        "VERBOSE" },
  203.     { "VERBO",        "VERBOSE" },
  204.     { "VERB",        "VERBOSE" },
  205.     { "VER",        "VERBOSE" },
  206.     { "VE",            "VERBOSE" },
  207.     { "ANS",        "ANSI" },
  208.     { "AN",            "ANSI" },
  209.     { "MONITO",        "MONITOR" },
  210.     { "MONIT",        "MONITOR" },
  211.     { "MONI",        "MONITOR" },
  212.     { "MON",        "MONITOR" },
  213.     { "MO",            "MONITOR" },
  214.     { "NOSPOO",        "NOSPOOF" },
  215.     { "NOSPO",        "NOSPOOF" },
  216.     { "NOSP",        "NOSPOOF" },
  217.     { "NOS",        "NOSPOOF" },
  218.     { "ZON",        "ZONE" },
  219.     { "ZO",            "ZONE" },
  220.     { "Z",            "ZONE" },
  221.     { "CONNECTE",        "CONNECTED" },
  222.     { "CONNECT",        "CONNECTED" },
  223.     { "CONNEC",        "CONNECTED" },
  224.     { "CONNE",        "CONNECTED" },
  225.     { "CONN",        "CONNECTED" },
  226.     { "CON",        "CONNECTED" },
  227.     { "CO",            "CONNECTED" },
  228.     { "GAG",        "GAGGED" },
  229.     { "MYOPI",        "MYOPIC" },
  230.     { "MYOP",        "MYOPIC" },
  231.     { "MYO",        "MYOPIC" },
  232.     { "MY",            "MYOPIC" },
  233.     { "TERS",        "TERSE" },
  234.     { "TER",        "TERSE" },
  235.     { "SUSPEC",        "SUSPECT" },
  236.     { "SUSPE",        "SUSPECT" },
  237.     { "SUSP",        "SUSPECT" },
  238.     { "SUS",        "SUSPECT" },
  239.     { "SU",            "SUSPECT" },
  240.     { "DEST_OK",        "DESTROY_OK" },
  241.     { "DESTROY_O",        "DESTROY_OK" },
  242.     { "DESTROY_",        "DESTROY_OK" },
  243.     { "DESTROY",        "DESTROY_OK" },
  244.     { "DESTRO",        "DESTROY_OK" },
  245.     { "DESTR",        "DESTROY_OK" },
  246.     { "DEST",        "DESTROY_OK" },
  247.     { "DES",        "DESTROY_OK" },
  248.     { "DE",            "DESTROY_OK" },
  249.     { "LISTENE",        "LISTENER" },
  250.     { "LISTEN",        "LISTENER" },
  251.     { "LISTE",        "LISTENER" },
  252.     { "LIST",        "LISTENER" },
  253.     { "LIS",        "LISTENER" },
  254.     { "PUPPE",        "PUPPET" },
  255.     { "PUPP",        "PUPPET" },
  256.     { "PUP",        "PUPPET" },
  257.     { "PU",            "PUPPET" },
  258.     { "P",            "PUPPET" },
  259.     { "ABOD",        "ABODE" },
  260.     { "ABO",        "ABODE" },
  261.     { "AB",            "ABODE" },
  262.     { "FLOATIN",        "FLOATING" },
  263.     { "FLOATI",        "FLOATING" },
  264.     { "FLOAT",        "FLOATING" },
  265.     { "FLOA",        "FLOATING" },
  266.     { "FLO",        "FLOATING" },
  267.     { "FL",            "FLOATING" },
  268.     { "F",            "FLOATING" },
  269.     { "JUMP_O",        "JUMP_OK" },
  270.     { "JUMP_",        "JUMP_OK" },
  271.     { "JUMP",         "JUMP_OK" },
  272.     { "JUM",        "JUMP_OK" },
  273.     { "JU",            "JUMP_OK" },
  274.     { "J",            "JUMP_OK" },
  275.     { "NO_TE",        "NO_TEL" },
  276.     { "NO_T",        "NO_TEL" },
  277.     { "TEMPL",        "TEMPLE" },
  278.     { "TEMP",        "TEMPLE" },
  279.     { "TEM",        "TEMPLE" },
  280.     { "TE",            "TEMPLE" },
  281.     { NULL,            NULL }
  282. };
  283.  
  284. /*---------------------------------------------------------------------------
  285.  * Flag hash table handlers 
  286.  */
  287.  
  288. static FLAG *flag_hash_lookup(name)
  289.      const char *name;
  290. {
  291.     FLAGENT *f;
  292.     FLAG *t;
  293.  
  294.     for (f = flag_hashtab[hash_fn(name, FLAG_HASH_MASK)];
  295.      f != NULL; f = f->next) {
  296.     if (!strcmp(name, f->name))
  297.         return f->entry;
  298.     }
  299.  
  300.     /* provided for backwards compatibility: type flag checking */
  301.     for (t = type_table; t->name != NULL; t++)
  302.     if (string_prefix(name, t->name))
  303.         return t;
  304.  
  305.     return NULL;
  306. }
  307.  
  308. static void flag_hash_insert(name, entry)
  309.      const char *name;
  310.      FLAG *entry;
  311. {
  312.     FLAGENT *new;
  313.     unsigned hashval;
  314.  
  315.     /* insert flag into hash table. Assume no duplicates. */
  316.  
  317.     new = (FLAGENT *) malloc(sizeof(FLAGENT));
  318.     new->name = (char *) strdup(name);
  319.     new->entry = entry;
  320.     hashval = hash_fn(name, FLAG_HASH_MASK);
  321.     new->next = flag_hashtab[hashval];
  322.     flag_hashtab[hashval] = new;
  323. }
  324.  
  325. void init_flag_hashtab()
  326. {
  327.     FLAG *f;
  328.     FLAG_ALIAS *a;
  329.  
  330.     /* do regular flags first */
  331.     for (f = flag_table; f->name; f++)
  332.     flag_hash_insert(f->name, f);
  333.  
  334.     /* now add in the aliases */
  335.     for (a = flag_alias_tab; a->alias; a++) {
  336.     if ((f = flag_hash_lookup(a->realname)) != NULL)
  337.         flag_hash_insert(a->alias, (FLAG *)f);
  338.     else
  339.         fprintf(stderr,
  340.             "FLAG INIT: flag alias %s matches no known flag.\n",
  341.             a->alias);
  342.     }
  343. }
  344.  
  345. /*---------------------------------------------------------------------------
  346.  * Other functions dealing with flags
  347.  */
  348.  
  349. int can_set_flag(player, thing, flagp, negate)
  350.      dbref player;
  351.      dbref thing;
  352.      FLAG *flagp;
  353.      int negate;
  354. {
  355.     /* returns 1 if player can set a flag on thing. */
  356.  
  357.     if (!flagp || !GoodObject(player) || !GoodObject(thing))
  358.     return 0;
  359.  
  360.     if (flagp->perms & F_INTERNAL)
  361.     return 0;
  362.  
  363.     if ((flagp->type != NOTYPE) && (flagp->type != Typeof(thing)))
  364.     return 0;
  365.  
  366. #ifdef INHERIT_FLAG
  367.     if ((flagp->perms & F_INHERIT) && !Wizard(player) &&
  368.     (!Inherit(player) || !Owns(player, thing)))
  369.     return 0;
  370. #endif
  371.  
  372.     if ((flagp->flag == GOING) && (flagp->type == NOTYPE) &&
  373.     ((Typeof(thing) != TYPE_ROOM) || !negate))
  374.     return 0;
  375.  
  376.     if (flagp->perms & F_ANY)
  377.     return 1;
  378.     if ((flagp->perms & F_WIZARD) && !Wizard(player))
  379.     return 0;
  380.     else if ((flagp->perms & F_ROYAL) && !Hasprivs(player))
  381.     return 0;
  382.     else if ((flagp->perms & F_GOD) && !God(player))
  383.     return 0;
  384.  
  385.     /* special case for the privileged flags. We do need to check
  386.      * for royalty setting flags on objects they don't own, because
  387.      * the controls check will not stop the flag set if the royalty
  388.      * player is in a zone. Also, only God can set the wizbit on
  389.      * players.
  390.      */
  391.     if (God(player))        /* God can do (almost) anything */
  392.     return 1;
  393.  
  394.     /* Make sure we don't accidentally permission-check toggles when
  395.      * checking priv bits.
  396.      */
  397.     if (flagp->type == NOTYPE) {
  398.  
  399.     /* A wiz can set things he owns WIZ, but can't reset his own bit. */
  400.     if (flagp->flag == WIZARD) {
  401.         return (Wizard(player) && Owns(player, thing) &&
  402.             (Typeof(thing) != TYPE_PLAYER));
  403.     }
  404.  
  405.     /* Wizards can set or unset anything royalty. Royalty can set anything
  406.      * they own royalty, but cannot reset their own bits. */
  407. #ifdef ROYALTY_FLAG
  408.     if (flagp->flag == ROYALTY) {
  409.         return (Wizard(player) ||
  410.             (Royalty(player) && Owns(player, thing) &&
  411.              (Typeof(thing) != TYPE_PLAYER)));
  412.     }
  413. #endif
  414.     } else if (Wizard(thing) && (flagp->flag == PLAYER_GAGGED) &&
  415.            (flagp->type == TYPE_PLAYER)) {
  416.     return 0;        /* can't gag wizards */
  417.     }
  418.  
  419.     return 1;
  420. }
  421.  
  422. const char *unparse_flags(thing, player)
  423.     dbref thing;
  424.     dbref player;
  425. {
  426.   /* print out the flag symbols (letters) */
  427.  
  428.   static char buf[BUFFER_LEN];
  429.   char *p;
  430.   const char *type_codes = "R-EP";
  431.   FLAG *f;
  432.   int t;
  433.  
  434.   p = buf;
  435.   t = Typeof(thing);
  436.   if (t != TYPE_THING)
  437.     *p++ = type_codes[t];
  438.  
  439.   /* get generic flags */
  440.   for (f = flag_table; f->type == NOTYPE; f++) {
  441.     if (Flags(thing) & f->flag)
  442.       *p++ = f->letter;
  443.   }
  444.  
  445.   /* exits have no special flags. This may change in the future */
  446.   if (t == TYPE_EXIT) {
  447.     *p = '\0';
  448.     return buf;
  449.   }
  450.  
  451.   /* go to beginning of list of flags for the type and print flags for
  452.    * that type.
  453.    */
  454.   while (f->type != t)   
  455.     f++;
  456.   for ( ; f->type == t; f++) {
  457.     if (Toggles(thing) & f->flag)
  458.       *p++ = f->letter;
  459.   }
  460.  
  461.   /* we don't want the player to see the SUSPECT flag if he's not priv'ed.
  462.    * As long as it's the last in the list, we can get rid of it simply by
  463.    * putting our terminating null one character early.
  464.    */
  465.   if ((t == TYPE_PLAYER) && (Toggles(thing) & PLAYER_SUSPECT) &&
  466.       !See_All(player))
  467.     *(--p) = '\0';
  468.   else
  469.     *p = '\0';
  470.  
  471.   return buf;
  472. }
  473.  
  474. #ifdef FLAGS_ON_EXAMINE
  475. const char *flag_description(player, thing)
  476.      dbref player;
  477.      dbref thing;
  478. {
  479.   static char buf[BUFFER_LEN];
  480.   char fbuf[BUFFER_LEN];
  481.   char *bp;
  482.   FLAG *f;
  483.   int t;
  484.  
  485.   t = Typeof(thing);
  486.  
  487.   strcpy(buf, "Type: ");
  488.   switch (t) {
  489.   case TYPE_ROOM:
  490.     strcat(buf, "Room");
  491.     break;
  492.   case TYPE_EXIT:
  493.     strcat(buf, "Exit");
  494.     break;
  495.   case TYPE_THING:
  496.     strcat(buf, "Thing");
  497.     break;
  498.   case TYPE_PLAYER:
  499.     strcat(buf, "Player");
  500.     break;
  501.   default:
  502.     strcat(buf, "***UNKNOWN TYPE***");
  503.     break;
  504.   }
  505.   strcat(buf, " Flags:");
  506.  
  507.   bp = fbuf;
  508.  
  509.   /* get generic flags */
  510.   for (f = flag_table; f->type == NOTYPE; f++) {
  511.     if (Flags(thing) & f->flag) {
  512.       safe_chr(' ', fbuf, &bp);
  513.       safe_str(f->name, fbuf, &bp);
  514.     }
  515.   }
  516.  
  517.   /* go to beginning of list of flags for the type and print flags for
  518.    * that type.
  519.    */
  520.   while ((f->type != t) && (f->type != NOTYPE))
  521.     f++;
  522.   for ( ; f->type == t; f++) {
  523.     if (Toggles(thing) & f->flag) {
  524.       safe_chr(' ', fbuf, &bp);
  525.       safe_str(f->name, fbuf, &bp);
  526.     }
  527.   }
  528.  
  529.   /* we don't want the player to see the SUSPECT flag if he's not priv'ed.
  530.    * As long as it's the last in the list, we can get rid of it simply by
  531.    * putting our terminating null one word early.
  532.    */
  533.   if ((t == TYPE_PLAYER) && (Toggles(thing) & PLAYER_SUSPECT) &&
  534.       !See_All(player)) {
  535.     do {
  536.       bp--;
  537.     } while (!isspace(*bp));
  538.   }
  539.   *bp = '\0';
  540.  
  541.   /* no length checking needed. We're never going to have an overflow. */
  542.   sprintf(buf, "%s%s", buf, fbuf); 
  543.   return buf;
  544. }
  545. #endif                /* FLAGS_ON_EXAMINE */
  546.  
  547. object_flag_type letter_to_flag(c, type, toggle)
  548.      char c;
  549.      int type;
  550.      int *toggle;
  551. {
  552.     /* convert letter to flag */
  553.  
  554.     FLAG *f;
  555.  
  556.     *toggle = 0;
  557.  
  558.     /* try generic flags */
  559.     for (f = flag_table; f->type == NOTYPE; f++) {
  560.     if (c == f->letter)
  561.         return (f->flag);
  562.     }
  563.  
  564.     /* try type-specific flags */
  565.  
  566.     *toggle = 1;
  567.     while ((f->type != type) && (f->type != NOTYPE))
  568.     f++;
  569.  
  570.     for ( ; f->type != NOTYPE; f++) {
  571.     if (c == f->letter)
  572.         return (f->flag);
  573.     }
  574.     return -1;
  575. }
  576.  
  577. object_flag_type find_flag(name, type, toggle, is_conf)
  578.      const char *name;
  579.      int type;
  580.      int *toggle;
  581.      int is_conf;
  582. {
  583.     /* given a flag name and an object type, return a flag, and set the
  584.      * value of toggle to 0 if flag, 1 if toggle. We also check if it's
  585.      * a legal flag to set, if it's a conf flag set.
  586.      */
  587.  
  588.     FLAG *f;
  589.     
  590.     *toggle = 0;
  591.  
  592.     if ((f = flag_hash_lookup(upcasestr(name))) == NULL)
  593.     return -1;
  594.  
  595.     if (is_conf && ((f->perms == F_INTERNAL) || (f->flag == GOING)))
  596.     return -1;
  597.  
  598.     if (f->type == NOTYPE) {
  599.     return f->flag;
  600.     } else {
  601.     *toggle = 1;
  602.     if (type != f->type) {
  603.         if (is_conf)
  604.         return -2;
  605.         else
  606.         return -1;
  607.     } else {
  608.         return f->flag;
  609.     }
  610.     }
  611.     return f->flag;        /* NOTREACHED */
  612. }
  613.  
  614. void decompile_flags(player, thing, name)
  615.      dbref player;
  616.      dbref thing;
  617.      const char *name;
  618. {
  619.   /* print out the flags for a decompile */
  620.  
  621.   FLAG *f;
  622.   int t, ok;
  623.  
  624.   t = Typeof(thing);
  625.   ok = !Suspect(thing);
  626.  
  627.   /* do generic flags */
  628.   for (f = flag_table; f->type == NOTYPE; f++)
  629.     if ((Flags(thing) & f->flag) && (f->perms & F_INTERNAL))
  630.       notify(player, tprintf("@set %s = %s", name, f->name));
  631.  
  632.   /* do normal flags */
  633.   while ((f->type != t) && (f->type != NOTYPE))
  634.     f++;
  635.   for ( ; f->type == t; f++)
  636.     if ((Toggles(thing) & f->flag) && (ok || (f->flag != PLAYER_SUSPECT)))
  637.       notify(player, tprintf("@set %s = %s", name, f->name));
  638. }
  639.  
  640. int convert_flags(player, s, p_mask, p_toggle, p_type)
  641.      dbref player;
  642.      char *s;
  643.      object_flag_type *p_mask;
  644.      object_flag_type *p_toggle;
  645.      object_flag_type *p_type;
  646. {
  647.   /* convert flags for search */
  648.  
  649.   FLAG *f;
  650.   object_flag_type mask, toggle, type;
  651.   int done;
  652.   mask = toggle = 0;
  653.   type = NOTYPE;
  654.  
  655.   while (s && *s) {
  656.  
  657.     done = 0;
  658.  
  659.     switch (*s) {
  660.     case 'P':
  661.       type = TYPE_PLAYER;
  662.       break;
  663.     case 'R':
  664.       type = TYPE_ROOM;
  665.       break;
  666.     case 'E':
  667.       type = TYPE_EXIT;
  668.       break;
  669.     default:
  670.  
  671.       /* check generic flags first */
  672.       for (f = flag_table; (f->type == NOTYPE) && !done; f++) {
  673.     if (*s == f->letter) {
  674.       mask |= f->flag;
  675.       done = 1;
  676.     }
  677.       }
  678.  
  679.       /* try type-specific flags */
  680.  
  681.       /* if we have a type, start searching from that type */
  682.       if (!done && (type != NOTYPE))
  683.     while ((f->type != type) && (f->type != NOTYPE))
  684.       f++;
  685.  
  686.       for ( ; !done && (f->type != NOTYPE); f++) {
  687.     if (*s == f->letter) {
  688.       /* if we don't have a type yet, we do now. If we do, we need
  689.        * to check for a conflict.
  690.        */
  691.       if (type == NOTYPE) {
  692.         type = f->type;
  693.         toggle |= f->flag;
  694.         done = 1;
  695.       } else if (type != f->type) {
  696.         notify(player, tprintf("Type conflict with flag '%c'.", *s));
  697.         return 0;
  698.       }
  699.     }
  700.       }
  701.  
  702.       /* if we get this far and still haven't found anything, error. */
  703.       if (!done) {
  704.     notify(player, tprintf("%c: unknown flag.", *s));
  705.     return 0;
  706.       }
  707.     }
  708.     s++;
  709.   }
  710.  
  711.   *p_mask = mask;
  712.   *p_toggle = toggle;
  713.   *p_type = type;
  714.   return 1;
  715. }
  716.  
  717. void set_flag(player, thing, flag, negate, hear, listen)
  718.      dbref player;
  719.      dbref thing;
  720.      const char *flag;
  721.      int negate;
  722.      int hear;
  723.      int listen;
  724. {
  725.   /* attempt to set a flag on an object */
  726.  
  727.   FLAG *f;
  728.   char tbuf1[BUFFER_LEN];
  729.  
  730.   if ((f = flag_hash_lookup(upcasestr(flag))) == NULL) {
  731.     notify(player, "I don't recognize that flag.");
  732.     return;
  733.   }
  734.  
  735.   if (!can_set_flag(player, thing, f, negate)) {
  736.     notify(player, "Permission denied.");
  737.     return;
  738.   }
  739.  
  740.   if (negate) {
  741.     
  742.     /* reomve the flag */
  743.     if (f->type == NOTYPE)
  744.       Flags(thing) &= ~(f->flag);
  745.     else
  746.       Toggles(thing) &= ~(f->flag);
  747.  
  748.     /* log if necessary */
  749.     if ((f->flag == WIZARD) && (f->type == NOTYPE))
  750.       do_log(LT_WIZ, player, thing, "WIZFLAG RESET");
  751. #ifdef ROYALTY_FLAG
  752.     else if ((f->flag == ROYALTY) && (f->type == NOTYPE))
  753.       do_log(LT_WIZ, player, thing, "ROYAL FLAG RESET");
  754. #endif
  755.  
  756.     /* those who unDARK return to the RWHO */
  757.     if ((f->flag == DARK) && (f->type == NOTYPE) &&
  758.     (Typeof(thing) == TYPE_PLAYER))
  759.     hide_player(thing, 0);
  760.     
  761.     /* notify the area if something stops listening */
  762.     if ((Typeof(thing) == TYPE_THING) && (f->type == TYPE_THING) &&
  763.     (((f->flag == THING_PUPPET) && !listen && !Hearer(thing)) ||
  764.      ((f->flag == THING_LISTEN) && !hear && !Listener(thing)))) {
  765.       sprintf(tbuf1, "%s loses its ears and becomes deaf.", Name(thing));
  766.       notify_except(Contents(Location(thing)), 0, tbuf1);
  767.     }
  768.     if ((f->flag == AUDIBLE) && (f->type == NOTYPE)) {
  769.       switch (Typeof(thing)) {
  770.       case TYPE_EXIT:
  771.     if (Flags(Exits(thing)) & AUDIBLE) {
  772.       sprintf(tbuf1, "Exit %s is no longer broadcasting.", Name(thing));
  773.       notify_except(Contents(Exits(thing)), 0, tbuf1);
  774.     }
  775.     break;
  776.       case TYPE_ROOM:
  777.     notify_except(Contents(thing), 0, 
  778.               "Audible exits in this room have been deactivated.");
  779.     break;
  780.       case TYPE_THING:
  781.       case TYPE_PLAYER:
  782.     notify_except(Contents(thing), 0,
  783.               "This room is no longer broadcasting.");
  784.     break;
  785.       }
  786.     }
  787.  
  788.     if (((f->flag == QUIET) && (f->type == NOTYPE)) ||
  789.     (!Quiet(player) && !Quiet(thing)))
  790.       notify(player, "Flag reset.");
  791.  
  792.   } else {
  793.  
  794.     /* set the flag */
  795.     if (f->type == NOTYPE)
  796.       Flags(thing) |= f->flag;
  797.     else
  798.       Toggles(thing) |= f->flag;
  799.  
  800.     /* log if necessary */
  801.     if ((f->flag == WIZARD) && (f->type == NOTYPE))
  802.       do_log(LT_WIZ, player, thing, "WIZFLAG SET");
  803. #ifdef ROYALTY_FLAG
  804.     if ((f->flag == ROYALTY) && (f->type == NOTYPE))
  805.       do_log(LT_WIZ, player, thing, "ROYAL FLAG SET");
  806. #endif
  807.  
  808.     /* DARK players should be treated as logged out */
  809.     if ((f->flag == DARK) && (f->type == NOTYPE) &&
  810.     (Typeof(thing) == TYPE_PLAYER))
  811.     hide_player(thing, 1);
  812.  
  813.     /* notify area if something starts listening */
  814.     if ((Typeof(thing) == TYPE_THING) && (f->type == TYPE_THING) &&
  815.     ((f->flag == THING_PUPPET) || (f->flag == THING_LISTEN)) &&
  816.     !hear && !listen) {
  817.       sprintf(tbuf1,"%s grows ears and can now hear.", Name(thing));
  818.       notify_except(Contents(Location(thing)), NOTHING, tbuf1);
  819.     }
  820.     
  821.     /* notify for audible exits */
  822.     if ((f->flag == AUDIBLE) && (f->type == NOTYPE)) {
  823.       switch (Typeof(thing)) {
  824.       case TYPE_EXIT:
  825.     if (db[db[thing].exits].flags & AUDIBLE) {
  826.       sprintf(tbuf1, "Exit %s is now broadcasting.", Name(thing));
  827.       notify_except(Contents(Exits(thing)), NOTHING, tbuf1);
  828.     }
  829.     break;
  830.       case TYPE_ROOM:
  831.     notify_except(Contents(thing), NOTHING,
  832.               "Audible exits in this room have been activated.");
  833.     break;
  834.       case TYPE_PLAYER:
  835.       case TYPE_THING:
  836.     notify_except(Contents(thing), NOTHING,
  837.               "This room is now broadcasting.");
  838.     break;
  839.       }
  840.     }
  841.  
  842.     if (((f->flag == QUIET) && (f->flag == NOTYPE)) ||
  843.     (!Quiet(player) && !Quiet(thing)))
  844.       notify(player, "Flag set.");
  845.   }
  846. }
  847.